import 'dart:io';

import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:yinshui_caiying/config/config.dart';
import 'package:yinshui_caiying/http/auth.dart';
import 'package:yinshui_caiying/http/log.dart';
import 'package:yinshui_caiying/http/proxy.dart';
import 'package:yinshui_caiying/http/response.dart';

class Http {
  //超时时间
  static const int _CONNECTTIMEOUT = 10000;
  static const int _RECEIVETIMEOUT = 3000;

  //单例模式
  static final Http _instance = Http._init();
  factory Http() => _instance;
  late Dio _dio;
  late BaseOptions _options;

  //构造函数
  Http._init() {
    _options = new BaseOptions(
        baseUrl: Config.BASE_URL,
        //连接时间为5秒
        connectTimeout: _CONNECTTIMEOUT,
        //响应时间为3秒
        receiveTimeout: _RECEIVETIMEOUT,
        //设置请求头
        headers: {"resource": "android"},
        //默认值是"application/json; charset=utf-8",Headers.formUrlEncodedContentType会自动编码请求体.
        contentType: Headers.formUrlEncodedContentType,
        //共有三种方式json,bytes(响应字节),stream（响应流）,plain
        responseType: ResponseType.json);
    _dio = new Dio(_options);
    //设置Cookie
    _dio.interceptors.add(CookieManager(CookieJar()));

    //添加日志拦截器
    _dio.interceptors.add(HttpLog());

    //添加请求头拦截器
    _dio.interceptors.add(AuthInterceptor());

    //添加返回拦截器
    _dio.interceptors.add(ResponseInterceptors());

    //是否启用代理
    // 在调试模式下需要抓包调试，所以我们使用代理，并禁用HTTPS证书校验
    if (Proxy.PROXY_ENABLE) {
      (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
          (client) {
        client.findProxy = (uri) {
          return "PROXY $Proxy.PROXY_IP:$Proxy.PROXY_PORT";
        };
        //代理工具会提供一个抓包的自签名证书，会通不过证书校验，所以我们禁用证书校验
        client.badCertificateCallback =
            (X509Certificate cert, String host, int port) => true;
      };
    }
  }

  //get请求方法
  get(url, {data, options, cancelToken}) async {
    late Response response;
    try {
      response = await _dio.get(url,
          queryParameters: data, options: options, cancelToken: cancelToken);
    } on DioError catch (e) {}
    return response.data;
  }

  // static  Options _postOptions=const Options(contentType: 'application/json' );
  //post请求
  post(url, {data, options, queryParameters, cancelToken}) async {
    late Response response;

    try {
      var optionsNew = null;
      optionsNew =
          options == null ? Options(contentType: 'application/json') : options;
      response = await _dio.post(url,
          data: data,
          options: optionsNew,
          queryParameters: queryParameters,
          cancelToken: cancelToken);
    } on DioError catch (e) {}
    return response.data;
  }

  delete(url, {data, options, queryParameters, cancelToken}) async {
    late Response response;

    try {
      var optionsNew = null;
      optionsNew =
          options == null ? Options(contentType: 'application/json') : options;
      response = await _dio.delete(url,
          data: data,
          options: optionsNew,
          queryParameters: queryParameters,
          cancelToken: cancelToken);
    } on DioError catch (e) {}
    return response.data;
  }

  put(url, {data, options, queryParameters, cancelToken}) async {
    late Response response;

    try {
      var optionsNew = null;
      optionsNew = options == null
          ? Options(
              contentType: 'application/json',
            )
          : options;
      response = await _dio.put(url,
          data: data,
          options: optionsNew,
          queryParameters: queryParameters,
          cancelToken: cancelToken);
    } on DioError catch (e) {}
    return response.data;
  }

  //post Form请求
  postForm(url, {data, options, cancelToken}) async {
    late Response response;
    try {
      response = await _dio.post(url,
          data: data, options: options, cancelToken: cancelToken);
    } on DioError catch (e) {}
    return response.data;
  }

  //下载文件
  downLoadFile(urlPath, savePath) async {
    late Response response;
    try {
      response = await _dio.download(urlPath, savePath,
          onReceiveProgress: (int count, int total) {
        print('$count $total');
      });
    } on DioError catch (e) {}
    return response.data;
  }

  //取消请求
  cancleRequests(CancelToken token) {
    token.cancel("cancelled");
  }
}
